home *** CD-ROM | disk | FTP | other *** search
/ Giga Games 1 / Giga Games.iso / net / hack / 3_1_3 / sys / winnt / nttty.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-07  |  13.7 KB  |  632 lines

  1. /*    SCCS Id: @(#)nttty.c    3.1    93/07/04
  2. /* Copyright (c) NetHack PC Development Team 1993    */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. /* tty.c - (Windows NT) version */
  6. /*                                                  
  7.  * Initial Creation - Michael Allison 93/01/31 
  8.  *
  9.  */
  10.  
  11. #ifdef WIN32CON
  12.  
  13. #define NEED_VARARGS /* Uses ... */
  14. #include "hack.h"
  15. #include "wintty.h"
  16. #include <sys\types.h>
  17. #include <sys\stat.h>
  18. #pragma pack(8)
  19. #include <windows.h>
  20. #include <wincon.h>
  21. #pragma pack()
  22.  
  23. void FDECL(cmov, (int, int));
  24. void FDECL(nocmov, (int, int));
  25.  
  26. /*
  27.  * The following WIN32 Console API routines are used in this file.
  28.  *
  29.  * CreateFile
  30.  * GetConsoleScreenBufferInfo
  31.  * GetStdHandle
  32.  * SetConsoleCursorPosition
  33.  * SetConsoleTextAttribute
  34.  * PeekConsoleInput
  35.  * ReadConsoleInput
  36.  * WriteConsoleOutputCharacter
  37.  */
  38.  
  39. /* Win32 Console handles for input and output */
  40. HANDLE hConIn;
  41. HANDLE hConOut;
  42.  
  43. /* Win32 Screen buffer,coordinate,console I/O information */
  44. CONSOLE_SCREEN_BUFFER_INFO csbi;
  45. COORD ntcoord;
  46. INPUT_RECORD ir;
  47.  
  48. /* Flag for whether NetHack was launched via progman, not command line.
  49.  * The reason we care at all, is so that we can get
  50.  * a final RETURN at the end of the game when launched from progman
  51.  * to prevent the scoreboard (or panic message :-|) from vanishing
  52.  * immediately after it is displayed, yet not bother when started
  53.  * from the command line. 
  54.  */
  55. int ProgmanLaunched;
  56.  
  57. # ifdef TEXTCOLOR
  58. char ttycolors[MAXCOLORS];
  59. static void NDECL(init_ttycolor);
  60. # endif
  61.  
  62. static char nullstr[] = "";
  63. char erase_char,kill_char;
  64. /* extern int LI, CO; */    /* decl.h does this alreay */
  65.  
  66. /*
  67.  * Called after returning from ! or ^Z
  68.  */
  69. void
  70. gettty(){
  71.     register int i;
  72.  
  73.     erase_char = '\b';
  74.     kill_char = 21;        /* cntl-U */
  75.     flags.cbreak = TRUE;
  76. #ifdef TEXTCOLOR
  77.     init_ttycolor();
  78. #endif
  79. }
  80.  
  81. /* reset terminal to original state */
  82. void
  83. settty(s)
  84. const char *s;
  85. {
  86.     end_screen();
  87.     if(s) raw_print(s);
  88. }
  89.  
  90. /* called by init_nhwindows() and resume_nhwindows() */
  91. void
  92. setftty()
  93. {
  94.     start_screen();
  95. }
  96.  
  97. /*
  98.  *  Keyboard translation tables.
  99.  *  (Adopted from the MSDOS port)
  100.  */
  101.  
  102. #define KEYPADLO    0x47
  103. #define KEYPADHI    0x53
  104.  
  105. #define PADKEYS     (KEYPADHI - KEYPADLO + 1)
  106. #define iskeypad(x)    (KEYPADLO <= (x) && (x) <= KEYPADHI)
  107.  
  108. /*
  109.  * Keypad keys are translated to the normal values below.
  110.  * Shifted keypad keys are translated to the
  111.  *    shift values below.
  112.  */
  113.  
  114. static const struct pad {
  115.     char normal, shift, cntrl;
  116. } keypad[PADKEYS] = {
  117.             {'y', 'Y', C('y')},        /* 7 */
  118.             {'k', 'K', C('k')},        /* 8 */
  119.             {'u', 'U', C('u')},        /* 9 */
  120.             {'m', C('p'), C('p')},        /* - */
  121.             {'h', 'H', C('h')},        /* 4 */
  122.             {'g', 'g', 'g'},        /* 5 */
  123.             {'l', 'L', C('l')},        /* 6 */
  124.             {'p', 'P', C('p')},        /* + */
  125.             {'b', 'B', C('b')},        /* 1 */
  126.             {'j', 'J', C('j')},        /* 2 */
  127.             {'n', 'N', C('n')},        /* 3 */
  128.             {'i', 'I', C('i')},        /* Ins */
  129.             {'.', ':', ':'}            /* Del */
  130. }, numpad[PADKEYS] = {
  131.             {'7', M('7'), '7'},        /* 7 */
  132.             {'8', M('8'), '8'},        /* 8 */
  133.             {'9', M('9'), '9'},        /* 9 */
  134.             {'m', C('p'), C('p')},        /* - */
  135.             {'4', M('4'), '4'},        /* 4 */
  136.             {'g', 'G', 'g'},        /* 5 */
  137.             {'6', M('6'), '6'},        /* 6 */
  138.             {'p', 'P', C('p')},        /* + */
  139.             {'1', M('1'), '1'},        /* 1 */
  140.             {'2', M('2'), '2'},        /* 2 */
  141.             {'3', M('3'), '3'},        /* 3 */
  142.             {'i', 'I', C('i')},        /* Ins */
  143.             {'.', ':', ':'}            /* Del */
  144. };
  145. /*
  146.  * Unlike Ctrl-letter, the Alt-letter keystrokes have no specific ASCII
  147.  * meaning unless assigned one by a keyboard conversion table
  148.  * To interpret Alt-letters, we use a
  149.  * scan code table to translate the scan code into a letter, then set the
  150.  * "meta" bit for it.  -3.
  151.  */
  152. #define SCANLO        0x10
  153.  
  154. static const char scanmap[] = {     /* ... */
  155.     'q','w','e','r','t','y','u','i','o','p','[',']', '\n',
  156.     0, 'a','s','d','f','g','h','j','k','l',';','\'', '`',
  157.     0, '\\', 'z','x','c','v','b','n','m',',','.','?'    /* ... */
  158. };
  159.  
  160. #define inmap(x)    (SCANLO <= (x) && (x) < SCANLO + SIZE(scanmap))
  161.  
  162. int
  163. tgetch()
  164. {
  165.     int valid = 0;
  166.     int metaflags = 0;
  167.     int count;
  168.     unsigned short int scan;
  169.     unsigned char ch;
  170.     unsigned long shiftstate;
  171.     int altseq;
  172.     const struct pad *kpad;
  173.     char keymess[100];
  174.  
  175.     shiftstate = 0L;
  176.     valid = 0;
  177.     while (!valid)
  178.     {
  179.        ReadConsoleInput(hConIn,&ir,1,&count);
  180.        if ((ir.EventType == KEY_EVENT) && ir.Event.KeyEvent.bKeyDown) {
  181.         ch    = ir.Event.KeyEvent.uChar.AsciiChar;
  182.         scan  = ir.Event.KeyEvent.wVirtualScanCode;
  183.         shiftstate = ir.Event.KeyEvent.dwControlKeyState;
  184.         altseq=(shiftstate & (LEFT_ALT_PRESSED|RIGHT_ALT_PRESSED)) && inmap(scan);
  185.         if (ch || (iskeypad(scan)) || altseq)
  186.             valid = 1;
  187.        }
  188.     }
  189.     if (valid) {
  190.             /*
  191.         * shiftstate can be checked to see if various special
  192.             * keys were pressed at the same time as the key.
  193.             * Currently we are using the ALT & SHIFT & CONTROLS.
  194.             *
  195.             *           RIGHT_ALT_PRESSED, LEFT_ALT_PRESSED,
  196.             *           RIGHT_CTRL_PRESSED, LEFT_CTRL_PRESSED,
  197.             *           SHIFT_PRESSED,NUMLOCK_ON, SCROLLLOCK_ON,
  198.             *           CAPSLOCK_ON, ENHANCED_KEY
  199.             *
  200.             * are all valid bit masks to use on shiftstate.
  201.             * eg. (shiftstate & LEFT_CTRL_PRESSED) is true if the
  202.             *      left control key was pressed with the keystroke.
  203.             */
  204.             if (iskeypad(scan)) {
  205.                 kpad = flags.num_pad ? numpad : keypad;
  206.                 if (shiftstate & SHIFT_PRESSED) {
  207.                     ch = kpad[scan - KEYPADLO].shift;
  208.                 }
  209.                 else if (shiftstate & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) {
  210.                     ch = kpad[scan - KEYPADLO].cntrl;
  211.                 }
  212.                 else {
  213.                     ch = kpad[scan - KEYPADLO].normal;
  214.                 }
  215.             }
  216.             else if (shiftstate & (LEFT_ALT_PRESSED|RIGHT_ALT_PRESSED)) { /* ALT sequence */
  217.                     if (inmap(scan))
  218.                         ch = scanmap[scan - SCANLO];
  219.                     ch = (isprint(ch) ? M(ch) : ch);
  220.             }
  221.             return (ch == '\r') ? '\n' : ch;
  222.     }
  223. }
  224.  
  225. int
  226. kbhit()
  227. {
  228.     int done = 0;    /* true =  "stop searching"        */
  229.     int retval;    /* true =  "we had a match"        */
  230.     int count;
  231.     unsigned short int scan;
  232.     unsigned char ch;
  233.     unsigned long shiftstate;
  234.     int altseq;
  235.         
  236.     done = 0;
  237.     retval = 0;
  238.     while (!done)
  239.     {
  240.         count = 0;
  241.         PeekConsoleInput(hConIn,&ir,1,&count);
  242.         if (count > 0) {
  243.         ch    = ir.Event.KeyEvent.uChar.AsciiChar;
  244.         scan  = ir.Event.KeyEvent.wVirtualScanCode;
  245.         shiftstate = ir.Event.KeyEvent.dwControlKeyState;
  246.         altseq=(shiftstate & (LEFT_ALT_PRESSED|RIGHT_ALT_PRESSED)) && inmap(scan);
  247.         if (((ir.EventType == KEY_EVENT) && ir.Event.KeyEvent.bKeyDown) &&
  248.              (ch || (iskeypad(scan)) || altseq)) {
  249.             done = 1;        /* Stop looking         */
  250.             retval = 1;         /* Found what we sought */
  251.         }
  252.         else /* Discard it, its an insignificant event */
  253.             ReadConsoleInput(hConIn,&ir,1,&count);
  254.         } else  /* There are no events in console event queue */ {
  255.         done = 1;      /* Stop looking               */
  256.         retval = 0;
  257.         }
  258.     }
  259.     return retval;
  260. }
  261.  
  262. /* called by init_tty in wintty.c for WIN32CON port only */
  263. void
  264. nttty_open()
  265. {
  266.         HANDLE hStdOut;
  267.         long cmode;
  268.         long mask;
  269.         unsigned int codepage;
  270.         
  271.         /* The following 6 lines of code were suggested by 
  272.          * Bob Landau of Microsoft WIN32 Developer support,
  273.          * as the only current means of determining whether
  274.          * we were launched from the command prompt, or from
  275.          * the NT program manager. M. Allison
  276.          */
  277.         hStdOut = GetStdHandle( STD_OUTPUT_HANDLE );
  278.         GetConsoleScreenBufferInfo( hStdOut, &csbi);
  279.         ProgmanLaunched = ((csbi.dwCursorPosition.X == 0) &&
  280.                            (csbi.dwCursorPosition.Y == 0));
  281.         if ((csbi.dwSize.X <= 0) || (csbi.dwSize.Y <= 0))
  282.             ProgmanLaunched = 0;
  283.  
  284.  
  285.         /* Obtain handles for the standard Console I/O devices */
  286.     hConIn = CreateFile("CONIN$",
  287.             GENERIC_READ |GENERIC_WRITE,
  288.             FILE_SHARE_READ |FILE_SHARE_WRITE,
  289.             NULL, OPEN_EXISTING, 0, NULL);                    
  290.     GetConsoleMode(hConIn,&cmode);
  291.     mask = ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT |
  292.            ENABLE_MOUSE_INPUT | ENABLE_ECHO_INPUT | ENABLE_WINDOW_INPUT;   
  293.     cmode &= ~mask;
  294.     SetConsoleMode(hConIn,cmode);
  295.     
  296.     hConOut = CreateFile("CONOUT$",
  297.             GENERIC_READ |GENERIC_WRITE,
  298.             FILE_SHARE_READ |FILE_SHARE_WRITE,
  299.             NULL, OPEN_EXISTING, 0, NULL);                            
  300.         
  301.     get_scr_size();
  302. }
  303.  
  304. void
  305. get_scr_size()
  306. {
  307.     if (GetConsoleScreenBufferInfo(hConOut,&csbi))
  308.     {
  309.         LI = csbi.dwSize.Y;
  310.         CO = csbi.dwSize.X;
  311.     }
  312.     else
  313.     {    
  314.         LI = 25;
  315.         CO = 80;
  316.     }
  317. }
  318.  
  319.  
  320. /* fatal error */
  321. /*VARARGS1*/
  322.  
  323. void
  324. error VA_DECL(const char *,s)
  325.     VA_START(s);
  326.     VA_INIT(s, const char *);
  327.     /* error() may get called before tty is initialized */
  328.     if (flags.window_inited) end_screen();
  329.     putchar('\n');
  330.     Vprintf(s,VA_ARGS);
  331.     putchar('\n');
  332.     VA_END();
  333.     exit(1);
  334. }
  335.  
  336.  
  337. void
  338. tty_startup(wid, hgt)
  339.     int *wid, *hgt;
  340. {
  341.     register int i;
  342.  
  343.     *wid = CO;
  344.     *hgt = LI;
  345. }
  346.  
  347. void
  348. tty_number_pad(state)
  349. int state;
  350. {
  351. }
  352.  
  353. void
  354. tty_start_screen()
  355. {
  356.     if (flags.num_pad) tty_number_pad(1);    /* make keypad send digits */
  357. }
  358.  
  359. void
  360. tty_end_screen()
  361. {
  362.     clear_screen();
  363. }
  364.  
  365. void
  366. nocmov(x, y)
  367. int x,y;
  368. {
  369.     ntcoord.X = x;
  370.     ntcoord.Y = y;
  371.     SetConsoleCursorPosition(hConOut,ntcoord);
  372. }
  373.  
  374. void
  375. cmov(x, y)
  376. register int x, y;
  377. {
  378.     ntcoord.X = x;
  379.     ntcoord.Y = y;
  380.     SetConsoleCursorPosition(hConOut,ntcoord);
  381.     ttyDisplay->cury = y;
  382.     ttyDisplay->curx = x;
  383. }
  384.  
  385. void
  386. xputc(c)
  387. char c;
  388. {
  389.     int count;
  390.  
  391.     ntcoord.X = ttyDisplay->curx;
  392.     ntcoord.Y = ttyDisplay->cury;
  393.     WriteConsoleOutputCharacter(hConOut,&c,1,ntcoord,&count);
  394. }
  395.  
  396. void
  397. xputs(s)
  398. const char *s;
  399. {
  400.     int count;
  401.     
  402.     ntcoord.X = ttyDisplay->curx;
  403.     ntcoord.Y = ttyDisplay->cury;
  404.     WriteConsoleOutputCharacter(hConOut,s,
  405.             strlen(s),ntcoord,&count);
  406. }
  407.  
  408. void
  409. cl_end()
  410. {
  411.         int count;
  412.  
  413.         ntcoord.X = ttyDisplay->curx;
  414.         ntcoord.Y = ttyDisplay->cury;
  415.         FillConsoleOutputCharacter(hConOut,' ',
  416.             CO - ntcoord.X,ntcoord,&count);
  417.         tty_curs(BASE_WINDOW, (int)ttyDisplay->curx+1,
  418.                         (int)ttyDisplay->cury);
  419. }
  420.  
  421.  
  422. void
  423. clear_screen()
  424. {
  425.     int count;
  426.  
  427.     ntcoord.X = 0;
  428.     ntcoord.Y = 0;
  429.     FillConsoleOutputCharacter(hConOut,' ',CO * LI,
  430.         ntcoord, &count);
  431.     home();
  432. }
  433.  
  434.  
  435. void
  436. home()
  437. {
  438.     tty_curs(BASE_WINDOW, 1, 0);
  439.     ttyDisplay->curx = ttyDisplay->cury = 0;
  440. }
  441.  
  442.  
  443. void
  444. backsp()
  445. {
  446.     DWORD count;
  447.  
  448.     GetConsoleScreenBufferInfo(hConOut,&csbi);
  449.     if (csbi.dwCursorPosition.X > 0)
  450.         ntcoord.X = csbi.dwCursorPosition.X-1;
  451.     ntcoord.Y = csbi.dwCursorPosition.Y;
  452.     WriteConsoleOutputCharacter(hConOut," ",1,ntcoord,&count);
  453.     SetConsoleCursorPosition(hConOut,ntcoord);    
  454. }
  455.  
  456. void
  457. tty_nhbell()
  458. {
  459.     if (flags.silent) return;
  460.     Beep(8000,500);
  461. }
  462.  
  463.  
  464. void
  465. tty_delay_output()
  466. {
  467.     /* delay 50 ms - uses ANSI C clock() function now */
  468.     clock_t goal;
  469.  
  470.     goal = 50 + clock();
  471.     while (goal > clock()) {
  472.         /* Do nothing */
  473.     }
  474. }
  475.  
  476. void
  477. cl_eos()
  478. {
  479.  
  480.         register int cy = ttyDisplay->cury+1;
  481.         while(cy <= LI-2) {
  482.             cl_end();
  483.             xputc('\n');
  484.             cy++;
  485.         }
  486.         cl_end();
  487.         tty_curs(BASE_WINDOW, (int)ttyDisplay->curx+1,
  488.                         (int)ttyDisplay->cury);
  489. }
  490.  
  491.  
  492. # ifdef TEXTCOLOR
  493. /*
  494.  * BLACK        0
  495.  * RED            1
  496.  * GREEN        2
  497.  * BROWN        3    low-intensity yellow
  498.  * BLUE            4
  499.  * MAGENTA         5
  500.  * CYAN            6
  501.  * GRAY            7    low-intensity white
  502.  * NO_COLOR        8
  503.  * ORANGE_COLORED    9
  504.  * BRIGHT_GREEN        10
  505.  * YELLOW        11
  506.  * BRIGHT_BLUE        12
  507.  * BRIGHT_MAGENTA      13
  508.  * BRIGHT_CYAN        14
  509.  * WHITE        15
  510.  * MAXCOLORS        16
  511.  * BRIGHT        8
  512.  */
  513.  
  514. static void
  515. init_ttycolor()
  516. {
  517.     ttycolors[BLACK] = FOREGROUND_GREEN|FOREGROUND_BLUE|FOREGROUND_RED;
  518.     ttycolors[RED] = FOREGROUND_RED;
  519.     ttycolors[GREEN] = FOREGROUND_GREEN;
  520.     ttycolors[BROWN] = FOREGROUND_GREEN|FOREGROUND_RED;
  521.     ttycolors[BLUE] = FOREGROUND_BLUE|FOREGROUND_INTENSITY;
  522.     ttycolors[MAGENTA] = FOREGROUND_BLUE|FOREGROUND_RED;
  523.     ttycolors[CYAN] = FOREGROUND_GREEN|FOREGROUND_BLUE;
  524.     ttycolors[GRAY] = FOREGROUND_GREEN|FOREGROUND_RED|FOREGROUND_BLUE;
  525.     ttycolors[BRIGHT] = FOREGROUND_GREEN|FOREGROUND_BLUE|FOREGROUND_RED|FOREGROUND_INTENSITY;
  526.     ttycolors[ORANGE_COLORED] = FOREGROUND_RED|FOREGROUND_INTENSITY;
  527.     ttycolors[BRIGHT_GREEN] = FOREGROUND_GREEN|FOREGROUND_INTENSITY;
  528.     ttycolors[YELLOW] = FOREGROUND_GREEN|FOREGROUND_RED|FOREGROUND_INTENSITY;
  529.     ttycolors[BRIGHT_BLUE] = FOREGROUND_BLUE|FOREGROUND_INTENSITY;
  530.     ttycolors[BRIGHT_MAGENTA] = FOREGROUND_BLUE|FOREGROUND_RED|FOREGROUND_INTENSITY;
  531.     ttycolors[BRIGHT_CYAN] = FOREGROUND_GREEN|FOREGROUND_BLUE;
  532.     ttycolors[WHITE] = FOREGROUND_GREEN|FOREGROUND_BLUE|FOREGROUND_RED|FOREGROUND_INTENSITY;
  533. }
  534.  
  535. # endif /* TEXTCOLOR */
  536.  
  537. int
  538. has_color(int color)
  539. {
  540. # ifdef TEXTCOLOR
  541.     return 1;
  542. # else
  543.     return 0;
  544. # endif 
  545. }
  546.  
  547. void
  548. term_end_attr(int attr)
  549. {
  550.     /* Mix all three colors for white on NT console */
  551.     SetConsoleTextAttribute(hConOut,
  552.         FOREGROUND_RED|FOREGROUND_BLUE|
  553.         FOREGROUND_GREEN);    
  554. }
  555.  
  556. void
  557. term_start_attr(int attr)
  558. {
  559.     switch(attr){
  560.  
  561.         case ATR_ULINE:
  562.         case ATR_BOLD:
  563.                 /* Mix all three colors for white on NT console */
  564.             SetConsoleTextAttribute(hConOut,
  565.             FOREGROUND_RED|FOREGROUND_BLUE|
  566.             FOREGROUND_GREEN|FOREGROUND_INTENSITY );
  567.                 break;
  568.         case ATR_BLINK:
  569.         case ATR_INVERSE:
  570.         default:
  571.                 term_end_attr(0);
  572.                 break;
  573.     }                
  574. }
  575.  
  576. void
  577. term_end_raw_bold(void)
  578. {
  579.     standoutend();    
  580. }
  581.  
  582. void
  583. term_start_raw_bold(void)
  584. {
  585.     standoutbeg();
  586. }
  587.  
  588. void
  589. term_start_color(int color)
  590. {
  591. # ifdef TEXTCOLOR
  592.     WORD attr;
  593.  
  594.         if (color >= 0 && color < MAXCOLORS) {
  595.             attr = ttycolors[color];
  596.         SetConsoleTextAttribute(hConOut,attr);
  597.     }
  598. # endif
  599. }
  600.  
  601. void
  602. term_end_color(void)
  603. {
  604. # ifdef TEXTCOLOR
  605.     SetConsoleTextAttribute(hConOut,
  606.         FOREGROUND_RED|FOREGROUND_BLUE|
  607.         FOREGROUND_GREEN);
  608. # endif       
  609. }
  610.  
  611.  
  612. void
  613. standoutbeg()
  614. {
  615.     /* Mix all three colors for white on NT console */
  616.     SetConsoleTextAttribute(hConOut,
  617.         FOREGROUND_RED|FOREGROUND_BLUE|
  618.         FOREGROUND_GREEN|FOREGROUND_INTENSITY );
  619. }
  620.  
  621.  
  622. void
  623. standoutend()
  624. {
  625.     /* Mix all three colors for white on NT console */
  626.     SetConsoleTextAttribute(hConOut,
  627.         FOREGROUND_RED|FOREGROUND_BLUE|
  628.         FOREGROUND_GREEN);
  629. }
  630.  
  631. #endif /* WIN32CON */
  632.